let logger = require("pomelo-logger").getLogger(__filename);
let DateUtil = require("../../../utils/dateUtil");
let Poker = require("../../../domain/poker/niuniu");
let Random = require("../../../utils/random");
let BaseTable = require("../base/yuanbaoTable");
let util = require("util");
let pomelo = require("pomelo");

const ACTION_INTERVAL = 15;

const NiuTypeMultipliers = [
    [],
    [1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 4, 5, 6, 8],
    [1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 4, 5, 6, 8]
];

let SoloGameTable = function () {
    BaseTable.call(this);
    this.dealerType = 2; //2. 抢庄
    this.multiplierType = 1; //1. 牛七 牛八 *2
    this.maxAuctionDealerMultiplier = 1;  //最大抢庄1, 2, 3
    this.dealerUid = 0;
    this.step = 0;  //1 等待抢庄, 2 等待下注, 3 等待组牌提交
    this.stepTS = 0;
};

util.inherits(SoloGameTable, BaseTable);

SoloGameTable.prototype.start = function () {
    BaseTable.prototype.start.call(this);
    let playingPlayers = this.getPlayingPlayers();
    let hands = Poker.dealCards(playingPlayers.length);
    let fee = this.getFee();
    for (let i = 0; i < playingPlayers.length; i++) {
        let player = playingPlayers[i];
        player.start(hands[i], fee);
    }
    this.broadCast("onSoloGameStart", {
        playerUids: playingPlayers.map(function (player) {
            return player.getUid();
        }),
        balances: playingPlayers.map(function (player) {
            return player.getBalance()
        })
    });
    let lastGameDealer = this.getPlayingPlayerByUid(this.dealerUid);
    this.dealerUid = 0;
    //抢庄
    this.step = 1;
    this.stepTS = DateUtil.nowMS();
    let allPlayers = this.getAllPlayers();
    allPlayers.forEach(function (player) {
        player.pushCards(4, playingPlayers[0].getUid());
    });
    this.broadCast("onNiuniuAuctionDealerStart", {
        step: this.step,
        countDown : this.calculateCountDown()
    });
};

SoloGameTable.prototype.getDealCardLength = function() {
    return 4;
};

SoloGameTable.prototype.calculateCountDown = function () {
    if (this.step <= 0 || this.step >= 4) {
        return 0;
    }
    if (this.stepTS === 0) {
        return 0;
    }
    let interval = ACTION_INTERVAL - DateUtil.getIntervalSec(this.stepTS);
    return interval <= 0 ? 0 : interval;
};

SoloGameTable.prototype.finish = function () {
    let playingPlayers = this.getPlayingPlayers();
    let niuResult = [];
    for (let i = 0; i < playingPlayers.length; i++) {
        niuResult[i] = Poker.calculateNiuResult(playingPlayers[i].getCards());
    }
    let targetUid = this.dealerUid;

    let targetNiuResult = {};
    let targetPlayerIndex = 0;
    for (let i = 0; i < niuResult.length; i++) {
        if (playingPlayers[i].getUid() === targetUid) {
            targetNiuResult = niuResult[i];
            targetPlayerIndex = i;
            break;
        }
    }

    let scores = [];
    let targetScore = 0;
    for (let i = 0; i < niuResult.length; i++) {
        let currentPlayer = playingPlayers[i];
        let score = 0;
        let multiplierForTarget = 0;
        multiplierForTarget = playingPlayers[targetPlayerIndex].getMultiplierForDealer();
        let multiplierForBet = currentPlayer.getMultiplierForBet();
        if (multiplierForTarget === 0) {
            multiplierForTarget = 1;
        }
        if (niuResult[i].power > targetNiuResult.power) {
            score = NiuTypeMultipliers[this.multiplierType][niuResult[i].type] *
                multiplierForBet *
                multiplierForTarget *
                this.multiplier *
                this.maxAuctionDealerMultiplier;
        } else if (niuResult[i].power < targetNiuResult.power) {
            score = - NiuTypeMultipliers[this.multiplierType][niuResult[targetPlayerIndex].type] *
                multiplierForBet *
                multiplierForTarget *
                this.multiplier *
                this.maxAuctionDealerMultiplier;
        }
        scores.push(score);
        targetScore = targetScore - score;
    }
    scores[targetPlayerIndex] = targetScore;

    let results = [];
    for (let i = 0; i < niuResult.length; i++) {
        let player = playingPlayers[i];
        player.finish(scores[i]);
        results.push({
            uid: player.getUid(),
            score: scores[i],
            niuniuType: niuResult[i].type,
            cards: niuResult[i].finalCards,
            balance: player.getBalance()
        });
    }

    this.broadCast("onSoloGameFinish", {
        results: results,
        targetUid: targetUid
    });

    //reset table
    this.playingFlag = 0;
    this.step = 0;
    this.stepTS = 0;
    this.players.forEach(function (player) {
        if (player != null) {
            player.resetInTable();
            player.clearReady();
            player.startGetReadyCountDown(16);
        }
    });
};

SoloGameTable.prototype.getStep = function () {
    return this.step;
};

SoloGameTable.prototype.getDealerType = function () {
    return this.dealerType;
};

SoloGameTable.prototype.getDealerUid = function () {
    return this.dealerUid;
};

SoloGameTable.prototype.betForDealer = function (player, multiplier) {
    player.betForDealer(multiplier);
    this.broadCast("onNiuniuPlayerBetForDealer", {
        uid: player.getUid(),
        multiplier: multiplier
    });
    this.checkNextRound();
};

SoloGameTable.prototype.bet = function (player, multiplier) {
    player.bet(multiplier);
    this.broadCast("onNiuniuPlayerBet", {
        uid: player.getUid(),
        multiplier: multiplier
    });
    this.checkNextRound();
};

SoloGameTable.prototype.commit = function (player) {
    player.commit();
    this.broadCast("onNiuniuPlayerCommit", {
        uid: player.getUid()
    });
    this.checkNextRound();
};

SoloGameTable.prototype.checkNextRound = function () {
    let self = this;
    let playingPlayers = this.getPlayingPlayers();
    let isAllActioned = true;
    playingPlayers.forEach(function (player) {
        if (player.getAction() <= 0) {
            isAllActioned = false;
        }
    });
    if (!isAllActioned) {
        return;
    }
    playingPlayers.forEach(function (player) {
        player.clearAction();
    });
    if (this.step === 1) {
        this.step = 2;
        this.stepTS = DateUtil.nowMS();
        let maxMultiplierForDealer = 0;
        playingPlayers.forEach(function (player) {
            if (player.getMultiplierForDealer() > maxMultiplierForDealer) {
                maxMultiplierForDealer = player.getMultiplierForDealer();
            }
        });
        let dealerCandidates = [];
        playingPlayers.forEach(function (player) {
            if (player.getMultiplierForDealer() === maxMultiplierForDealer) {
                dealerCandidates.push(player);
            }
        });
        let dealer = Random.choice(dealerCandidates);
        this.dealerUid = dealer.getUid();
        this.broadCast("onNiuniuChooseDealer", {
            uid: this.dealerUid
        });
        dealer.setAction();
        this.broadCast("onNiuniuBetStart", {
            step: this.step,
            countDown: this.calculateCountDown()
        });
    } else if (this.step === 2) {
        this.step = 3;
        this.stepTS = DateUtil.nowMS();
        let allPlayers = this.getAllPlayers();
        allPlayers.forEach(function (player) {
            player.pushCards(1, self.dealerUid);
        });
        this.broadCast("onNiuniuCommitStart", {
            step: this.step,
            countDown: this.calculateCountDown()
        });
    } else if (this.step === 3) {
        this.finish();
    }
};

SoloGameTable.prototype.toJSON = function () {
    let numOfCards = 0;
    if (this.step === 1) {
        numOfCards = 4;
    } else if (this.step === 2)  {
        //抢庄的时候有4张牌
        numOfCards = 4;
    } else if (this.step === 3) {
        numOfCards = 5;
    } else {
        numOfCards = 0;
    }
    let playersJSON = [];
    this.players.forEach(function (player) {
        if (player != null) {
            let playerJSON = player.toJSON();
            if (player.isReady()) {
                playerJSON['numOfCards'] = numOfCards;
            } else {
                playerJSON['numOfCards'] = 0;
            }
            playersJSON.push(playerJSON);
        }
    });
    return {
        tid: this.tid,
        code: this.code,
        ownerUid: this.creatorUid,
        dealerUid: this.dealerUid,
        multiplier: this.multiplier,
        step: this.step,
        stepCountDown: this.calculateCountDown(),
        playingFlag: this.playingFlag,
        maxPlayers: this.maxPlayers,
        dealerType: this.dealerType,
        multiplierType: this.multiplierType,
        maxAuctionDealerMultiplier: this.maxAuctionDealerMultiplier,
        players : playersJSON
    };
};

SoloGameTable.prototype.getResultJSON = function (results) {
    return {
        gid : this.gid,
        tid : this.tid,
        code : this.code,
        multiplier : this.multiplier,
        startTime : this.gameStartTime,
        endTime : DateUtil.nowMS(),
        dealerType : this.dealerType,
        multiplierType : this.NiuTypeMultiplierToString(this.multiplierType),
        maxAuctionDealerMultiplier : this.maxAuctionDealerMultiplier,
        results : results
    }
};

SoloGameTable.prototype.tick = function () {
    BaseTable.prototype.tick.call(this);
    if (!this.isValid()) {
        return;
    }
    if (this.playingFlag <= 0) {
        return;
    }
    if (this.step < 1 || this.step >= 4) {
        return;
    }
    if (this.calculateCountDown() > 0) {
        return;
    }
    let self = this;
    let playingPlayers = this.getPlayingPlayers();
    if (this.step === 1) {
        playingPlayers.forEach(function (player) {
            if (player.getAction() < 1) {
                player.betForDealer(0);
                self.broadCast("onNiuniuPlayerBetForDealer", {
                    uid: player.getUid(),
                    multiplier: 0
                });
            }
        });
        this.checkNextRound();
    } else if (this.step === 2) {
        playingPlayers.forEach(function (player) {
            if (player.getAction() < 1) {
                player.bet(1);
                self.broadCast("onNiuniuPlayerBet", {
                    uid: player.getUid(),
                    multiplier: 1
                });
            }
        });
        this.checkNextRound();
    } else if (this.step === 3) {
        playingPlayers.forEach(function (player) {
            if (player.getAction() < 1) {
                player.commit();
                self.broadCast("onNiuniuPlayerCommit", {
                    uid: player.getUid()
                });
            }
        });
        this.checkNextRound();
    }
};

SoloGameTable.prototype.onAddPlayer = function (player) {
    player.push("onInitializeSoloGameTable",
        {table: this.toJSON(), myCards: player.getDisplayCards(this)}
    );
    this.broadCastWithout("onAddOrUpdateSoloGamePlayer",
        {player : player.toJSON()}, player.getUid());
};

SoloGameTable.prototype.NiuTypeMultiplierToString = function (multiplierType) {
    let NiuTypeMultiplier = NiuTypeMultipliers[multiplierType] || [];
    return JSON.stringify(NiuTypeMultiplier);
};

module.exports.create = function (tableCfg) {
    let table = new SoloGameTable();
    table.tid = tableCfg['tid'];
    table.code = tableCfg['code'];
    table.room = tableCfg['room'];
    table.multiplier = table.room.multiplier;
    table.maxPlayers = 2;
    table.dealerType = 2;
    table.multiplierType = 1;
    table.maxAuctionDealerMultiplier = 1;
    table.visible = 0;
    table.creatorUid = tableCfg['creatorUid'];
    table.gid = tableCfg['gid'];
    table.createTime = DateUtil.nowMS();
    for (let i = 0; i < table.maxPlayers; i++) {
        table.players.push(null);
    }
    return table;
};

